// Copyright (c) 2024 IndustrialTBB Framework
// Licensed under MIT License

#ifndef ITBB_DEVICES_TBB_DEVICE_FACTORY_H_
#define ITBB_DEVICES_TBB_DEVICE_FACTORY_H_

#include <oneapi/tbb.h>

#include <functional>
#include <memory>
#include <string>
#include <unordered_map>

#include "itbb/devices/tbb_adwin_device.h"
#include "itbb/devices/tbb_device_interface.h"

namespace itbb {
// 设备类型枚举
enum class TbbDeviceType {
  kAdwin,
  kS7TCP,
  kS7Serial,
  kModbusTCP,
  kModbusRTU,
  kModbusASCII,
  kNiDaq,
  kOpcUa,
  kEtherCAT,
  kProfinet,
  kCustom
};

// 设备配置基类
class TbbDeviceConfig {
 public:
  virtual ~TbbDeviceConfig() = default;
  virtual TbbDeviceType GetDeviceType() const = 0;
  virtual std::string ToJsonString() const = 0;
  virtual bool FromJsonString(const std::string& json) = 0;
  virtual bool Validate() const = 0;
  virtual std::unique_ptr<TbbDeviceConfig> Clone() const = 0;
};

// 设备创建器类型定义
using TbbDeviceCreator = std::function<std::unique_ptr<ITbbIndustrialDevice>(
    const std::string&, const TbbDeviceConfig&)>;

// 设备验证器类型定义
using TbbConfigValidator = std::function<bool(const TbbDeviceConfig&)>;

// TBB原生的设备工厂
class TbbDeviceFactory {
 public:
  TbbDeviceFactory() { RegisterBuiltinDevices(); }

  ~TbbDeviceFactory() = default;

  // 注册设备创建器
  bool RegisterDeviceCreator(TbbDeviceType device_type,
                             TbbDeviceCreator creator,
                             TbbConfigValidator validator = nullptr) {
    CreatorMap::accessor creator_accessor;
    if (device_creators_.insert(creator_accessor, device_type)) {
      creator_accessor->second = std::move(creator);

      if (validator) {
        ValidatorMap::accessor validator_accessor;
        config_validators_.insert(validator_accessor, device_type);
        validator_accessor->second = std::move(validator);
      }

      return true;
    }

    return false;  // 设备类型已存在
  }

  // 注册自定义设备创建器
  bool RegisterCustomDeviceCreator(const std::string& device_type_name,
                                   TbbDeviceCreator creator,
                                   TbbConfigValidator validator = nullptr) {
    CustomCreatorMap::accessor creator_accessor;
    if (custom_device_creators_.insert(creator_accessor, device_type_name)) {
      creator_accessor->second = std::move(creator);

      if (validator) {
        CustomValidatorMap::accessor validator_accessor;
        custom_config_validators_.insert(validator_accessor, device_type_name);
        validator_accessor->second = std::move(validator);
      }

      return true;
    }

    return false;
  }

  // 创建设备
  std::unique_ptr<ITbbIndustrialDevice> CreateDevice(
      TbbDeviceType device_type, const std::string& device_id,
      const TbbDeviceConfig& config) {
    // 验证配置
    if (!ValidateConfig(device_type, config)) {
      throw std::invalid_argument("Invalid device configuration");
    }

    // 查找创建器
    CreatorMap::const_accessor accessor;
    if (device_creators_.find(accessor, device_type)) {
      try {
        return accessor->second(device_id, config);
      } catch (const std::exception& e) {
        throw std::runtime_error("Failed to create device: " +
                                 std::string(e.what()));
      }
    }

    throw std::invalid_argument("Unsupported device type");
  }

  // 创建自定义设备
  std::unique_ptr<ITbbIndustrialDevice> CreateCustomDevice(
      const std::string& device_type_name, const std::string& device_id,
      const TbbDeviceConfig& config) {
    // 验证配置
    if (!ValidateCustomConfig(device_type_name, config)) {
      throw std::invalid_argument("Invalid custom device configuration");
    }

    // 查找创建器
    CustomCreatorMap::const_accessor accessor;
    if (custom_device_creators_.find(accessor, device_type_name)) {
      try {
        return accessor->second(device_id, config);
      } catch (const std::exception& e) {
        throw std::runtime_error("Failed to create custom device: " +
                                 std::string(e.what()));
      }
    }

    throw std::invalid_argument("Unsupported custom device type: " +
                                device_type_name);
  }

  // 从JSON配置创建设备
  std::unique_ptr<ITbbIndustrialDevice> CreateDeviceFromJson(
      const std::string& device_id, const std::string& json_config) {
    // 解析JSON获取设备类型
    auto device_type = ParseDeviceTypeFromJson(json_config);
    auto config = CreateConfigFromJson(device_type, json_config);

    return CreateDevice(device_type, device_id, *config);
  }

  // 批量创建设备
  std::vector<std::unique_ptr<ITbbIndustrialDevice>> CreateDevicesBatch(
      const std::vector<std::tuple<TbbDeviceType, std::string,
                                   std::unique_ptr<TbbDeviceConfig>>>&
          device_specs) {
    std::vector<std::unique_ptr<ITbbIndustrialDevice>> devices(
        device_specs.size());

    // 使用TBB并行创建设备
    tbb::parallel_for(
        tbb::blocked_range<size_t>(0, device_specs.size()),
        [&](const tbb::blocked_range<size_t>& range) {
          for (size_t i = range.begin(); i != range.end(); ++i) {
            const auto& [device_type, device_id, config] = device_specs[i];
            try {
              devices[i] = CreateDevice(device_type, device_id, *config);
            } catch (const std::exception& e) {
              // 记录错误，但继续处理其他设备
              devices[i] = nullptr;
            }
          }
        });

    return devices;
  }

  // 获取支持的设备类型
  std::vector<TbbDeviceType> GetSupportedDeviceTypes() const {
    std::vector<TbbDeviceType> types;

    for (CreatorMap::const_iterator it = device_creators_.begin();
         it != device_creators_.end(); ++it) {
      types.push_back(it->first);
    }

    return types;
  }

  // 获取支持的自定义设备类型
  std::vector<std::string> GetSupportedCustomDeviceTypes() const {
    std::vector<std::string> types;

    for (CustomCreatorMap::const_iterator it = custom_device_creators_.begin();
         it != custom_device_creators_.end(); ++it) {
      types.push_back(it->first);
    }

    return types;
  }

  // 验证设备配置
  bool ValidateConfig(TbbDeviceType device_type,
                      const TbbDeviceConfig& config) const {
    // 检查配置类型是否匹配
    if (config.GetDeviceType() != device_type) {
      return false;
    }

    // 基本验证
    if (!config.Validate()) {
      return false;
    }

    // 使用注册的验证器
    ValidatorMap::const_accessor accessor;
    if (config_validators_.find(accessor, device_type)) {
      return accessor->second(config);
    }

    return true;  // 没有特定验证器，基本验证通过即可
  }

  // 验证自定义设备配置
  bool ValidateCustomConfig(const std::string& device_type_name,
                            const TbbDeviceConfig& config) const {
    // 基本验证
    if (!config.Validate()) {
      return false;
    }

    // 使用注册的验证器
    CustomValidatorMap::const_accessor accessor;
    if (custom_config_validators_.find(accessor, device_type_name)) {
      return accessor->second(config);
    }

    return true;
  }

  // 获取设备类型字符串表示
  static std::string DeviceTypeToString(TbbDeviceType device_type) {
    switch (device_type) {
      case TbbDeviceType::kAdwin:
        return "ADwin";
      case TbbDeviceType::kS7TCP:
        return "S7TCP";
      case TbbDeviceType::kS7Serial:
        return "S7Serial";
      case TbbDeviceType::kModbusTCP:
        return "ModbusTCP";
      case TbbDeviceType::kModbusRTU:
        return "ModbusRTU";
      case TbbDeviceType::kModbusASCII:
        return "ModbusASCII";
      case TbbDeviceType::kNiDaq:
        return "NI-DAQ";
      case TbbDeviceType::kOpcUa:
        return "OPC-UA";
      case TbbDeviceType::kEtherCAT:
        return "EtherCAT";
      case TbbDeviceType::kProfinet:
        return "PROFINET";
      case TbbDeviceType::kCustom:
        return "Custom";
      default:
        return "Unknown";
    }
  }

  // 从字符串解析设备类型
  static TbbDeviceType StringToDeviceType(const std::string& type_string) {
    static const std::unordered_map<std::string, TbbDeviceType> type_map = {
        {"ADwin", TbbDeviceType::kAdwin},
        {"S7TCP", TbbDeviceType::kS7TCP},
        {"S7Serial", TbbDeviceType::kS7Serial},
        {"ModbusTCP", TbbDeviceType::kModbusTCP},
        {"ModbusRTU", TbbDeviceType::kModbusRTU},
        {"ModbusASCII", TbbDeviceType::kModbusASCII},
        {"NI-DAQ", TbbDeviceType::kNiDaq},
        {"OPC-UA", TbbDeviceType::kOpcUa},
        {"EtherCAT", TbbDeviceType::kEtherCAT},
        {"PROFINET", TbbDeviceType::kProfinet},
        {"Custom", TbbDeviceType::kCustom}};

    auto it = type_map.find(type_string);
    return it != type_map.end() ? it->second : TbbDeviceType::kCustom;
  }

  // 创建默认配置
  std::unique_ptr<TbbDeviceConfig> CreateDefaultConfig(
      TbbDeviceType device_type) const {
    switch (device_type) {
      case TbbDeviceType::kAdwin:
        return CreateDefaultAdwinConfig();
      case TbbDeviceType::kS7TCP:
        return CreateDefaultS7Config();
      case TbbDeviceType::kModbusTCP:
        return CreateDefaultModbusConfig();
      // 其他设备类型...
      default:
        return nullptr;
    }
  }

  // 获取配置模板
  std::string GetConfigTemplate(TbbDeviceType device_type) const {
    auto config = CreateDefaultConfig(device_type);
    return config ? config->ToJsonString() : "{}";
  }

 private:
  using CreatorMap = tbb::concurrent_hash_map<TbbDeviceType, TbbDeviceCreator>;
  using ValidatorMap =
      tbb::concurrent_hash_map<TbbDeviceType, TbbConfigValidator>;
  using CustomCreatorMap =
      tbb::concurrent_hash_map<std::string, TbbDeviceCreator>;
  using CustomValidatorMap =
      tbb::concurrent_hash_map<std::string, TbbConfigValidator>;

  CreatorMap device_creators_;
  ValidatorMap config_validators_;
  CustomCreatorMap custom_device_creators_;
  CustomValidatorMap custom_config_validators_;

  // 注册内置设备
  void RegisterBuiltinDevices() {
    // 注册ADwin设备
    RegisterDeviceCreator(
        TbbDeviceType::kAdwin,
        [](const std::string& device_id, const TbbDeviceConfig& config)
            -> std::unique_ptr<ITbbIndustrialDevice> {
          const auto& adwin_config =
              dynamic_cast<const TbbAdwinConfig&>(config);
          return std::make_unique<TbbAdwinDevice>(device_id, adwin_config);
        },
        [](const TbbDeviceConfig& config) -> bool {
          return ValidateAdwinConfig(
              dynamic_cast<const TbbAdwinConfig&>(config));
        });

    // 注册其他内置设备类型...
    // RegisterDeviceCreator(TbbDeviceType::kS7TCP, ...);
    // RegisterDeviceCreator(TbbDeviceType::kModbusTCP, ...);
  }

  // ADwin配置验证
  static bool ValidateAdwinConfig(const TbbAdwinConfig& config) {
    // IP地址验证
    if (config.ip_address.empty()) {
      return false;
    }

    // 端口验证
    uint16_t port = config.port.load();
    if (port == 0 || port > 65535) {
      return false;
    }

    // 超时验证
    auto timeout = config.timeout.load();
    if (timeout < std::chrono::milliseconds(100) ||
        timeout > std::chrono::minutes(5)) {
      return false;
    }

    return true;
  }

  // 创建默认ADwin配置
  std::unique_ptr<TbbDeviceConfig> CreateDefaultAdwinConfig() const {
    auto config = std::make_unique<TbbAdwinConfig>();
    config->ip_address = "192.168.1.100";
    config->port.store(6543);
    config->timeout.store(std::chrono::milliseconds(5000));
    config->processor_number.store(1);
    config->use_encryption.store(false);
    config->enable_keepalive.store(true);
    config->keepalive_interval.store(std::chrono::milliseconds(30000));
    return config;
  }

  // 创建默认S7配置
  std::unique_ptr<TbbDeviceConfig> CreateDefaultS7Config() const {
    // S7配置实现
    return nullptr;  // 简化实现
  }

  // 创建默认Modbus配置
  std::unique_ptr<TbbDeviceConfig> CreateDefaultModbusConfig() const {
    // Modbus配置实现
    return nullptr;  // 简化实现
  }

  // 从JSON解析设备类型
  TbbDeviceType ParseDeviceTypeFromJson(const std::string& json_config) const {
    // JSON解析实现
    // 简化实现，实际需要JSON库
    return TbbDeviceType::kAdwin;
  }

  // 从JSON创建配置
  std::unique_ptr<TbbDeviceConfig> CreateConfigFromJson(
      TbbDeviceType device_type, const std::string& json_config) const {
    auto config = CreateDefaultConfig(device_type);
    if (config && !config->FromJsonString(json_config)) {
      throw std::invalid_argument("Invalid JSON configuration");
    }
    return config;
  }
};

// ADwin配置的具体实现
class TbbAdwinConfigImpl : public TbbDeviceConfig {
 public:
  TbbAdwinConfigImpl() = default;

  TbbDeviceType GetDeviceType() const override { return TbbDeviceType::kAdwin; }

  std::string ToJsonString() const override {
    // JSON序列化实现
    return R"({
      "type": "ADwin",
      "ip_address": ")" +
           ip_address + R"(",
      "port": )" +
           std::to_string(port.load()) + R"(,
      "timeout": )" +
           std::to_string(timeout.load().count()) + R"(,
      "processor_number": )" +
           std::to_string(processor_number.load()) + R"(,
      "use_encryption": )" +
           (use_encryption.load() ? "true" : "false") + R"(,
      "enable_keepalive": )" +
           (enable_keepalive.load() ? "true" : "false") + R"(,
      "keepalive_interval": )" +
           std::to_string(keepalive_interval.load().count()) + R"(
    })";
  }

  bool FromJsonString(const std::string& json) override {
    // JSON反序列化实现
    // 简化实现，实际需要JSON库
    return true;
  }

  bool Validate() const override {
    return !ip_address.empty() && port.load() > 0 && port.load() <= 65535 &&
           timeout.load() >= std::chrono::milliseconds(100);
  }

  std::unique_ptr<TbbDeviceConfig> Clone() const override {
    auto clone = std::make_unique<TbbAdwinConfigImpl>();
    clone->ip_address = ip_address;
    clone->port.store(port.load());
    clone->timeout.store(timeout.load());
    clone->processor_number.store(processor_number.load());
    clone->use_encryption.store(use_encryption.load());
    clone->enable_keepalive.store(enable_keepalive.load());
    clone->keepalive_interval.store(keepalive_interval.load());
    return clone;
  }

  // ADwin特定配置
  std::string ip_address;
  std::atomic<uint16_t> port{6543};
  std::atomic<std::chrono::milliseconds> timeout{
      std::chrono::milliseconds(5000)};
  std::string password;
  std::atomic<int> processor_number{1};
  std::atomic<bool> use_encryption{false};
  std::atomic<bool> enable_keepalive{true};
  std::atomic<std::chrono::milliseconds> keepalive_interval{
      std::chrono::milliseconds(30000)};
};

// 设备工厂的单例访问
class TbbDeviceFactoryManager {
 public:
  static TbbDeviceFactory& GetInstance() {
    static TbbDeviceFactory instance;
    return instance;
  }

  // 便捷的设备创建方法
  template <typename ConfigType>
  static std::unique_ptr<ITbbIndustrialDevice> CreateDevice(
      const std::string& device_id, const ConfigType& config) {
    return GetInstance().CreateDevice(config.GetDeviceType(), device_id,
                                      config);
  }

  // 便捷的批量设备创建方法
  template <typename ConfigContainer>
  static std::vector<std::unique_ptr<ITbbIndustrialDevice>> CreateDevicesBatch(
      const ConfigContainer& configs) {
    std::vector<std::tuple<TbbDeviceType, std::string,
                           std::unique_ptr<TbbDeviceConfig>>>
        specs;

    for (const auto& [device_id, config] : configs) {
      specs.emplace_back(config.GetDeviceType(), device_id, config.Clone());
    }

    return GetInstance().CreateDevicesBatch(specs);
  }

 private:
  TbbDeviceFactoryManager() = default;
};
}  // namespace itbb

#endif  // ITBB_DEVICES_TBB_DEVICE_FACTORY_H_
